package com.yuzhi.framework.handler.geometry;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.yuzhi.common.contant.Constants;
import io.vavr.control.Option;
import lombok.Data;
import lombok.experimental.Accessors;
import org.locationtech.jts.geom.*;

import java.util.*;
import java.util.stream.Collectors;

@Data
@Accessors(chain = true)
public class Coordinate {

    private static final GeometryFactory geometryFactory = new GeometryFactory();
    //@ApiModelProperty("纬度")
    private Double latitude;
    //@ApiModelProperty("经度")
    private Double longitude;

    public Point toPoint() {
        if (Objects.nonNull(latitude) && Objects.nonNull(longitude)) {
            return geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(longitude, latitude));
        }
        return null;
    }

    public static LineString toLineString(List<Coordinate> coordinates) {
        return Option.when(CollectionUtil.isNotEmpty(coordinates), coordinates)
                .map(cs -> geometryFactory.createLineString(io.vavr.collection.List.ofAll(coordinates)
                        .map(c -> new org.locationtech.jts.geom.Coordinate(c.getLongitude(), c.getLatitude()))
                        .toJavaArray(org.locationtech.jts.geom.Coordinate[]::new)))
                .getOrNull();
    }

    public static Geometry toMultiPolygon(List<Coordinate> coordinates) {
        if (CollectionUtil.isNotEmpty(coordinates)){
            if (epetition(coordinates)){
                coordinates.add(coordinates.get(0));
            }
            Polygon polygon = geometryFactory.createPolygon(io.vavr.collection.List.ofAll(coordinates)
                    .map(c -> new org.locationtech.jts.geom.Coordinate(c.getLongitude(), c.getLatitude()))
                    .toJavaArray(org.locationtech.jts.geom.Coordinate[]::new));
            Polygon[] polygons = new Polygon[1];
            polygons[0]=polygon;
            MultiPolygon multiPolygon = geometryFactory.createMultiPolygon(polygons);
            multiPolygon.setSRID(4490);
            return multiPolygon;
        }
        return null;
    }
    public static Coordinate from(Point point) {
        if (point != null) {
            return new Coordinate().setLongitude(point.getCoordinate().x).setLatitude(point.getCoordinate().y);
        }
        return null;
    }

    public static Point toPoint(Double lon, Double lat) {
        if (Objects.nonNull(lon) && Objects.nonNull(lat)) {
            return geometryFactory.createPoint(new org.locationtech.jts.geom.Coordinate(lon, lat));
        }
        return null;
    }

    public static List<Coordinate> from(LineString line) {
        if (line != null && ArrayUtil.isNotEmpty(line.getCoordinates())) {
            return Arrays.stream(line.getCoordinates()).map(coordinate -> new Coordinate().setLongitude(coordinate.getX()).setLatitude(coordinate.getY())).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    public static List<Coordinate> from(MultiLineString lines) {
        if (lines != null && ArrayUtil.isNotEmpty(lines.getCoordinates())) {
            return Arrays.stream(lines.getCoordinates()).map(coordinate -> new Coordinate().setLongitude(coordinate.getX()).setLatitude(coordinate.getY())).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

  /* public static List<Coordinate> from(Geometry geo) {
        if (geo != null && ArrayUtil.isNotEmpty(geo.getCoordinates())) {
            List<Coordinate>  coordinateList = Arrays.stream(geo.getCoordinates()).map(coordinate -> new Coordinate().setLongitude(coordinate.x).setLatitude(coordinate.y)).collect(Collectors.toList());
            //过滤重复的
            List<String> collect = coordinateList.stream().collect(Collectors.groupingBy(Coordinate::fetchGroupKey, Collectors.counting())).entrySet()
                    .stream().filter(entry -> entry.getValue() > 1).map(Map.Entry::getKey).collect(Collectors.toList());
            // 去重并重新设置userStatus的值
            if (CollectionUtils.isNotEmpty(collect)){
                collect.forEach(s -> distinctUserInfo(coordinateList,s));
                String[] split = collect.get(0).split("#");

                coordinateList.add(new Coordinate().setLatitude(Double.valueOf(split[0])).setLongitude(Double.valueOf(split[1])));
                coordinateList.add(new Coordinate().setLatitude(Double.valueOf(split[0])).setLongitude(Double.valueOf(split[1])));
            }

            return coordinateList;
        }
        return Collections.emptyList();
    }*/
    public static List<Coordinate> from(Polygon geo) {
        if (geo != null && ArrayUtil.isNotEmpty(geo.getCoordinates())) {
            return  Arrays.stream(geo.getCoordinates()).map(coordinate -> new Coordinate().setLongitude(coordinate.getX()).setLatitude(coordinate.getY())).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
    public static List<Coordinate> from(Geometry geo) {
        if (geo != null && ArrayUtil.isNotEmpty(geo.getCoordinates())) {
            return  Arrays.stream(geo.getCoordinates()).map(coordinate -> new Coordinate().setLongitude(coordinate.getX()).setLatitude(coordinate.getY())).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
    public static String fetchGroupKey(Coordinate coordinate){
        return coordinate.getLatitude() + "#" + coordinate.getLongitude();
    }
    /**
     * (经度,维度)
     *
     * @param point
     * @return
     */
    public static String lonAndLatStr(Point point) {
        return Objects.isNull(point) ? null : StrFormatter.format("({},{})", point.getCoordinate().x, point.getCoordinate().y);
    }


    private static void distinctUserInfo(List<Coordinate> list, String str) {
        String[] split = str.split("#");
        // 先取出来第一个
        Optional<Coordinate> first = list.stream().filter(coordinate -> coordinate.getLatitude().toString().equals(split[0])&&coordinate.getLongitude().toString().equals(split[1])).findFirst();
        // 再取出与之对应重复的
         if (first.isPresent()) {
            Coordinate coordinate = first.get();
            // 先将所有符合这个重复的userName的对象从源集合中删除
            list.removeIf(next -> next.getLatitude().equals(coordinate.getLatitude())&&next.getLongitude().equals(coordinate.getLongitude()));
            //再将取出来的第一个添加进去

        }
    }
    public static boolean epetition(List<Coordinate> list) {

        for (int i = 0; i < list.size()-1; i++) {

            for (int j = list.size() - 1; j > i; j--) {

                if (list.get(j).getLatitude().equals(list.get(i).getLatitude())
                        && list.get(j).getLongitude().equals(list.get(i).getLongitude())) {


                    list.remove(j);//删除重复的数据
                    return true;
                }
            }
        }
        return true;
    }


    public static String changeToDFM(double du) {
        int du1 = (int) du;
        double tp = (du - du1) * 60;
        int fen = (int) tp;
        String miao = String.format("%.2f", Math.abs(((tp - fen) * 60)));
        return du1 + "°" + Math.abs(fen) + "'" + miao + "\"";
    }
    public static double changeToDu(String dms) {
        if (dms == null) return 0;
        try {
            dms = dms.replace(" ", "");
            String[] str2 = dms.split("°");
            if (str2.length < 2) return 0;
            int d = Integer.parseInt(str2[0]);
            String[] str3 = str2[1].split("\'");
            if (str3.length < 2) return 0;
            int f = Integer.parseInt(str3[0]);
            String str4 = str3[1].substring(0, str3[1].length() - 1);
            double m = Double.parseDouble(str4);

            double fen = f + (m / 60);
            double du = (fen / 60) + Math.abs(d);
            if (d < 0) du = -du;
            return du;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static double changeCompanyToDu(String dms) {
        if (dms == null) return 0;
        try {
            dms = dms.replace(" ", "");
            String[] str2 = dms.split("°");
            if (str2.length < 2) return 0;
            int d = Integer.parseInt(str2[0]);
            String[] str3 = str2[1].split("′");
            if (str3.length < 2) return 0;
            int f = Integer.parseInt(str3[0]);
            String str4 = str3[1].substring(0, str3[1].length() - 1);
            double m = Double.parseDouble(str4);

            double fen = f + (m / 60);
            double du = (fen / 60) + Math.abs(d);
            if (d < 0) du = -du;
            return du;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
    public static void main(String[] args) {
        String s = changeToDFM(32.419);
        double v = changeToDu("119°48′21″");
        double v1 = changeToDu("32°15'07\"");
        System.out.println(v);
        System.out.println(v1);

    }

    /**
     * 根据类型,转换空间数据
     *
     * @param geometryStr
     * @return java.lang.Object
     * @author: Mario
     * @date: 2023/2/14
     */
    public static Object byTypeToData(String geometryStr) {
        if (geometryStr.startsWith(Constants.POINT_TYPE)) {
            List<String> pointList = CharSequenceUtil.split(geometryStr, Constants.SPACE_STR);
            return Coordinate.from(Coordinate.toPoint(Double.parseDouble(CharSequenceUtil.removePrefix(pointList.get(0), Constants.POINT_SPLIT)), Double.parseDouble(CharSequenceUtil.removeSuffix(pointList.get(1), ")"))));
        }
        if (geometryStr.startsWith(Constants.MULTI_LINE_STRING_TYPE)) {
            return handleLineOrPolygonVo(geometryStr, Constants.MULTI_LINE_STRING_TYPE_SPLIT, "))");
        }
        if (geometryStr.startsWith(Constants.MULTI_POLYGON_TYPE)) {
            return handleLineOrPolygonVo(geometryStr, Constants.MULTI_POLYGON_TYPE_SPLIT, ")))");
        }
        return geometryStr;
    }


    private static List<Coordinate> handleLineOrPolygonVo(String geometryStr, String preFixStr, String suffixStr) {
        String firstSplit = CharSequenceUtil.removePrefix(geometryStr, preFixStr);
        String twoSplit = CharSequenceUtil.removeSuffix(firstSplit, suffixStr);
        List<String> multiLineStringList = CharSequenceUtil.split(twoSplit, ",");
        List<Coordinate> lines = new ArrayList<>();
        multiLineStringList.forEach(line -> {
            String[] data = line.split(Constants.SPACE_STR);
            lines.add(new Coordinate().setLatitude(Double.parseDouble(data[1])).setLongitude(Double.parseDouble(data[0])));
        });
        return lines;
    }
}
